interface EventFace {
  on: (name: string, callback: Function) => void;
  off: (name: string, fn: Function) => void;
  emit: (name: string, ...args: Array<any>) => void;
  once: (name: string, fn: Function) => void;
}
/**
 * 事件列表
 */
interface List {
  [key: string]: Array<Function>;
}

class Dispatch implements EventFace {
  list: List;

  constructor() {
    this.list = {};
  }

  on(name: string, callback: Function) {
    let callbackList = this.list[name] || [];

    callbackList.push(callback);

    this.list[name] = callbackList;
  }

  off(name: string, fn?: Function) {
    let eventName = this.list[name];

    if(eventName && !fn) {
      this.list[name] = []
    }

    if (name && fn) {
      let index = eventName.findIndex((eventFn) => eventFn === fn);

      if (index !== -1) {
        eventName.splice(index, 1);
      }
    }
  }

  emit(name: string, ...args: Array<any>) {
    let fnList = this.list[name];

    if (fnList) {
      fnList.forEach((fn) => {
        fn.apply(this, args);
      });
    }
  }

  once(name: string, fn: Function) {
    let innerFn = (...args: Array<any>) => {
      fn.apply(this, args);

      this.off(name, innerFn);
    };

    this.on(name, innerFn);
  }
}

const p = new Dispatch()

p.on('zhang', (args:Array<any>) => {
  console.log('张--',args);
})

p.off('zhang')


p.emit('zhang', 1,2,3)

p.once('一次', () => {
  console.log('只监听一次');
})

p.emit('一次')
p.emit('一次')


